import { tr } from '@config/tr';
import { filter, findIndex, forEach, forOwn, map, omit, remove } from 'lodash';
import { computed, reactive, ref, watch } from 'vue';

export default function useEvent(players: players): useEventReturn & ThisType<player> {
    const eId = ref(0);
    const Event: useEventReturn = {
        eId,
        stack: reactive<ev[]>([]),
        handles: computed(() => {
            const _handles: handles = {};
            forEach(players, player => {
                forOwn(player.skills.value, skill => {
                    const { owner, trigger } = skill;
                    if (trigger) {
                        forOwn(trigger, (phase, executor) => {
                            forEach(phase, phase => {
                                if (!_handles[phase]) {
                                    _handles[phase] = [];
                                }
                                const rest = omit(skill, 'trigger');
                                const index = findIndex(_handles[phase], i => i[0].owner === owner);
                                if (index !== -1) {
                                    _handles[phase][index].push(rest);
                                } else {
                                    _handles[phase].push([rest]);
                                }
                            });
                        });
                    }
                });
            });
            return _handles;
        }),
        curEv: ref<ev>({} as ev),
        curPhase: ref<phase>('' as phase),
        curFilterHandles: computed(() => {
            if (Event.handles.value[Event.curPhase.value]) {
                return map(Event.handles.value[Event.curPhase.value], skills =>
                    filter(
                        skills,
                        skill => Event.curEv.value.player === skill.owner || skill.global === true,
                    ),
                );
            }
            return [];
        }),
        getPlayer(seat) {
            return players[seat];
        },
        create(type, e) {
            let progress: progress;
            switch (type) {
                // 创建伤害结算流程
                case 'damage':
                    progress = [
                        'source.damageWhen',
                        'target.woundedWhen',
                        'source.damageAfter',
                        'target.woundedContent',
                        'target.woundedAfter',
                    ];
                    break;
                // 创建阶段结算流程
                case 'phase':
                    progress = [
                        'target.roundBegin',
                        'target.phasePrepare',
                        'target.phaseJudgeBegin',
                        'target.phaseJudgeContent',
                        'target.phaseJudgeEnd',
                        'target.phaseDrawBegin',
                        'target.phaseDrawContent',
                        'target.phaseDrawEnd',
                        'target.phaseUseBegin',
                        'target.phaseUseContent',
                        'target.phaseUseEnd',
                        'target.phaseDiscardBegin',
                        'target.phaseDiscardContent',
                        'target.phaseDiscardEnd',
                        'target.phaseEnd',
                        'target.roundEnd',
                    ];
                    break;
                default:
                    progress = [];
                    break;
            }
            Event.push(e, progress);
        },
        push(e, progress) {
            const arr: ev[] = [];
            const id = eId.value++;

            // 这里可以用set方式来保持e的引用地址不变
            forEach(progress, i => {
                const iarr = i.split('.') as [executor, phase];
                const [executor, phase] = iarr;
                const target: ev = {
                    id,
                    phase,
                    player: e[executor as executor]!,
                    e,
                    finish() {
                        // 事件取消即移除其在事件池中的剩余子事件
                        remove(Event.stack, item => item.id === id);
                        console.log(`事件 ${id}号 已取消`);
                    },
                };
                const handler: ProxyHandler<ev> = {
                    get(target, propKey) {
                        if (propKey in e) {
                            return Reflect.get(e, propKey);
                        }
                        return Reflect.get(target, propKey);
                    },
                    set(target, propKey, value) {
                        if (propKey in e) {
                            return Reflect.set(e, propKey, value);
                        }
                        return Reflect.set(target, propKey, value);
                    },
                };
                const ev: ev = new Proxy(target, handler);
                arr.push(ev);
            });
            Event.stack.unshift(...arr);
        },
        async iter() {
            while (Event.stack.length) {
                const ev = Event.stack.shift()!;
                if (ev.phase.endsWith('Content')) {
                    const player = Event.getPlayer(ev.player);
                    await player[ev.phase as phase & keyof player](ev);
                } else {
                    await Event.trigger(ev.phase, ev);
                }
            }
        },
        async trigger(phase, ev) {
            Event.curPhase.value = phase;
            Event.curEv.value = ev;
            const skillsArr = Event.curFilterHandles;
            if (skillsArr.value.length) {
                // 这里保证同一阶段的技能或者新增的同一阶段技能可以正常释放
                for (const i of skillsArr.value) {
                    for (const skill of i) {
                        // if (skillsArr.value[i].length - j === 1) {
                        // await Event.askEvalSkill(skillsArr.value[i], e);
                        // } else {
                        // await Event.askChooseSkill(choosed, e);
                        // }

                        const player = Event.getPlayer(skill.owner);
                        console.log(`${tr(player.name.value)}发动了【${tr(skill.name)}】`);
                        await skill.content!.call(player, ev);
                    }
                    // for (const skill of skills) {

                    // }
                }
            }
        },
    };
    watch(
        () => Event.stack.length,
        (newVal, oldVal) => {
            if (oldVal === 0 && newVal !== 0) {
                console.log('事件栈开始iter...');
                Event.iter();
            }
        },
    );
    window.e = Event;
    return Event;
}
